/**
 * 自动刷新Token，
 *
 * 当刷新token过程中，需要token的接口处于等待队列
 */

import { SilentAuthLogin } from "@/api/login";
import type { TRequestOptins, TRequestParams } from "./request";

// 尝试次数
let count = 0;
// 单次最大尝试次数
const maxAuthTimes = 1;

// 单个阶段，尝试次数，达到2次后，不再尝试刷新，等手动登录；
let compensationCount = 0;

// 重置
function resetCount() {
  count = 0;
}

// 是否正在登录授权
let isAuthorizing = false;

// 等待队列
const fetchStackList: Array<Function> = [];

// 登录
const authLogin = () => {
  if (count >= maxAuthTimes) {
    // 超过重连次数后，reject所有请求
    isAuthorizing = false;
    resetCount();
    // @ts-expect-error
    fetchStackList.forEach((fn) => fn.reject());
    fetchStackList.length = 0;
  } else {
    count++;
    SilentAuthLogin().then(
      (type: "pending" | "success") => {
        if (type === "success") {
          console.log("===登录成功");
          console.log("fetchStackList", [...fetchStackList]);
          // 登录成功，
          resetCount();
          compensationCount = 0;
          isAuthorizing = false;
          fetchStackList.forEach((fn) => fn());
          fetchStackList.length = 0;
        } else {
          console.log("正在登录中...");
        }
      },
      // catch: 再自行一次
      () => authLogin()
    );
  }
};

// 把后续请求放入队列
const pushFetchToStack = (
  request,
  requestParams: TRequestParams,
  requestOptions: TRequestOptins | undefined = undefined,
  resolve: any,
  reject: any
) => {
  const fetch = () =>
    toFetch(request, requestParams, requestOptions, resolve, reject);

  fetch.reject = reject;
  // 存储当前请求信息
  fetchStackList.push(fetch);
};

//
const toFetch = (
  request,
  requestParams,
  requestOptions,
  resolve,
  reject,
  flag?: boolean
) => {
  request(requestParams, requestOptions).then(resolve, (err) => {
    if (compensationCount < 2 && err?.code === 401) {
      // token过期，待重新登录授权
      if (flag) {
        pushFetchToStack(
          request,
          requestParams,
          requestOptions,
          resolve,
          reject
        );
      }

      // 记录单次阶段次数
      compensationCount++;
      authLogin();
    } else {
      reject(err);
    }
  });
};

// 刷新Token请求出入函数
const autoRefreshAuthTokenFetch = (
  request,
  requestParams: TRequestParams,
  requestOptions?: TRequestOptins
) => {
  return new Promise((resolve, reject) => {
    // 当前请求需要token && 正在登录授权中
    if (
      requestOptions?.token !== false &&
      isAuthorizing &&
      compensationCount < 2
    ) {
      // 存储当前请求信息
      pushFetchToStack(request, requestParams, requestOptions, resolve, reject);
    } else {
      // 不需要token || 有token
      toFetch(request, requestParams, requestOptions, resolve, reject, true);
    }
  });
};

export default autoRefreshAuthTokenFetch;
